package com.westcom.vulb.bean;

import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Calendar;
import java.util.Date;

import android.graphics.Bitmap;
import android.os.Handler;
import android.os.Message;
import android.os.Parcel;
import android.os.Parcelable;

import com.j256.ormlite.field.DatabaseField;
import com.j256.ormlite.table.DatabaseTable;
import com.westcom.vulb.application.GlobalContext;
import com.westcom.vulb.logic.account;
import com.westcom.vulb.logic.card;
import com.westcom.vulb.logic.category;
import com.westcom.vulb.logic.resource;
import com.westcom.vulb.logic.sheet;
import com.westcom.vulb.protocal.http.Response;

@DatabaseTable(tableName="session")
public class Session implements Parcelable {
    @DatabaseField
    protected int uid;
    @DatabaseField
    protected String sessionid;
    @DatabaseField
    protected long loginTime;
    @DatabaseField
    protected String maccount;
    @DatabaseField
    protected String pwd;
    
    private String msaveDir = "";
    private String mImageThumbnailDir = "";
    private String mImageDir = "";
    private String mOtherResDir = "";
    private String mSheetDir = "";
    private String mCategoryDir = "";
    private String mCardDir = "";
    private String mProfileImageDir = "";
    
    private static final String user_data_dir = "userdata/";
    
    private static final String image_thumbnail_dir = "image_thumbnail/";
    
    private static final String image_dir = "image/";
    
    private static final String other_resource_dir = "other_resource/";
    
    private static final String sheet_dir = "sheet/";
    
    private static final String category_dir = "category/";
    
    private static final String card_dir = "card/";
    
    private static final String profile_image_dir = "profileImage/";
    
    private final static int THUMBNAIL_REQUEST = 0;
    private final static int IMAGE_REQUEST = 1;
    private final static int OTHER_RES_REQUEST = 2;
    private final static int PROFILE_IMAGE_REQUEST = 3;
    
    public Session()
    {}
    public Session(int uid,String sessionid,Calendar loginTime,String account,String pwd)
    {
    	this.uid = uid;
    	this.sessionid = sessionid;
    	this.loginTime = loginTime.getTime().getTime();
    	this.maccount = account;
    	this.pwd = pwd;
    	Init();
    }
    private void Init()
    {
    	this.msaveDir = GlobalContext.getInstance().getRootDir() + user_data_dir + maccount+"/";
    	File f = new File(msaveDir);
    	if(!f.exists())
    	{
    		f.mkdirs();
    	}
    	this.mImageThumbnailDir = msaveDir + image_thumbnail_dir;
    	f = new File(mImageThumbnailDir);
    	if(!f.exists())
    	{
    		f.mkdirs();
    	}
    	
    	this.mImageDir = msaveDir + image_dir;
    	f = new File(mImageDir);
    	if(!f.exists())
    	{
    		f.mkdirs();
    	}
    	
    	this.mOtherResDir = msaveDir + other_resource_dir;
    	f = new File(mOtherResDir);
    	if(!f.exists())
    	{
    		f.mkdirs();
    	}
    	
    	this.mSheetDir = msaveDir + sheet_dir;
    	f = new File(mSheetDir);
    	if(!f.exists())
    	{
    		f.mkdirs();
    	}
    	
    	this.mCategoryDir = msaveDir + category_dir;
    	f = new File(mCategoryDir);
    	if(!f.exists())
    	{
    		f.mkdirs();
    	}
    	
    	this.mCardDir = msaveDir + card_dir;
    	f = new File(mCardDir);
    	if(!f.exists())
    	{
    		f.mkdirs();
    	}
    	
    	this.mProfileImageDir = GlobalContext.getInstance().getRootDir() + profile_image_dir;
    	f = new File(mProfileImageDir);
    	if(!f.exists())
    	{
    		f.mkdirs();
    	}
    }
    public int getUid() 
    {
        return uid;
    }
    public void setUid(int uid) 
    {
        this.uid = uid;
    }
    
    public String getSessionid() 
    {
        return sessionid;
    }
    public void setSessionid(String sessionid) 
    {
        this.sessionid = sessionid;
    }
    
    public Calendar getLoginTime() {
    	Calendar c = Calendar.getInstance();
    	c.setTimeInMillis(loginTime);
        return c;
    }
    public void setLoginTime(Calendar loginTime) 
    {
        this.loginTime = loginTime.getTime().getTime();
    }
    
    public String getAccont()
    {
    	return maccount;
    }
    public void setAccont(String account)
    {
    	this.maccount = account;
    }
    
    public String getpwd()
    {
    	return pwd;
    }
    public void setpwd(String pwd)
    {
    	this.pwd = pwd;
    }
    public void setSaveDir(String dir)
    {
    	this.msaveDir = dir;
    }
    public String getSaveDir()
    {
    	return this.msaveDir;
    }
    @Override
    public int describeContents() {
        // TODO Auto-generated method stub
        return 0;
    }
    
    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(uid);
        dest.writeString(sessionid);
        dest.writeLong(loginTime);
        dest.writeString(maccount);
        dest.writeString(pwd);
    }
    
    public static final Parcelable.Creator<Session> CREATOR = new Parcelable.Creator<Session>() 
    {
        @Override
        public Session createFromParcel(Parcel source) {
        	Calendar c = Calendar.getInstance();
        	c.setTime(new Date(source.readLong()));
            Session s = new Session(source.readInt(),source.readString(),c,source.readString(),source.readString());
            return s;
        }

        @Override
        public Session[] newArray(int size) {
            return new Session[size];
        }
    };
    private String checkLoaclCache(String dir,String tag)
    {
    	String ret = null;
    	File[] fs= new File(dir).listFiles();
    	for(File f:fs)
		{
			String path = f.getName();
			if(path.startsWith(tag)&&!f.isDirectory())
			{
				ret = f.getAbsolutePath();
			}
		}
    	return ret;
    }
    
    public int getResource(int res_id,int type,Message msg)//type   0:thumbnail   1:image   2:other
    {
    	new resourceWorker(res_id,type,msg,this.sessionid).start();
    	return 0;
    }
    public class resourceWorker extends Thread
    {
    	private int resId = 0;
    	private int resType = -1;
    	private Message resMsg = null;
    	public resourceWorker(int res_id,int type,Message msg,String sessionId)
    	{
    		resId = res_id;
    		resType = type;
    		resMsg = msg;
    	}
    	@Override
    	public void run()
    	{
    		resMsg.arg2 = resType;
    		switch(resType)
    		{
	    		case THUMBNAIL_REQUEST://thumbnail
	    		{
	    			String filePath = checkLoaclCache(mImageThumbnailDir,""+resId);//check local cache
	    	    	if(null != filePath)
	    	    	{
	    	    		resMsg.obj =  new getResourceResponse(resId,null,filePath);
	    	    		resMsg.arg1 = Response.SUCCESS;
	    	    		resMsg.sendToTarget();
	    	    		return;
	    	    	}
	    			Response response = resource.getInstance().ReferenceThumbnailImage(sessionid,resId);
	    			if(response.errno != Response.SUCCESS)
	    			{
	    				resMsg.obj = new getResourceResponse(resId,response,filePath);
		            	resMsg.arg1 = response.errno;
		            	resMsg.sendToTarget();
	    				return;
	    			}
	    			Bitmap Thumbnail = account.Base64Str2Bitmap((String)response.data.get("resourceData"));
	    			filePath = saveBitmap(Thumbnail,mImageThumbnailDir+resId+".png");
	    			resMsg.obj = new getResourceResponse(resId,response,filePath);
	            	resMsg.arg1 = response.errno;
	            	resMsg.sendToTarget();
	    		}break;
	    		case IMAGE_REQUEST://image
	    		{
	    			String filePath = checkLoaclCache(mImageDir,""+resId);//check local cache
	    	    	if(null != filePath)
	    	    	{
	    	    		resMsg.obj =  new getResourceResponse(resId,null,filePath);
	    	    		resMsg.arg1 = Response.SUCCESS;
	    	    		resMsg.sendToTarget();
	    	    		return;
	    	    	}
	    			Response response = resource.getInstance().ReferenceResourceInCard(sessionid,resId);
	    			if(response.errno != Response.SUCCESS)
	    			{
	    				resMsg.obj = new getResourceResponse(resId,response,filePath);
		            	resMsg.arg1 = response.errno;
		            	resMsg.sendToTarget();
	    				return;
	    			}
	    			String fileName = (String)response.data.get("fileName");
	    			//Bitmap source = account.Base64Str2Bitmap((String)response.data.get("resourceData"));
	    			filePath = writeString(mImageDir+resId+".dat",response.mOriginalStr);
	    			resMsg.obj = new getResourceResponse(resId,response,filePath);
	    			resMsg.arg1 = response.errno;
	    			if(null == filePath)
	    			{
	    				resMsg.arg1 = Response.LOCAL_ERROR;
	    			}
	            	resMsg.sendToTarget();
	    		}break;
	    		case OTHER_RES_REQUEST://other resource
	    		{
	    			String filePath = checkLoaclCache(mOtherResDir,""+resId);//check local cache
	    	    	if(null != filePath)
	    	    	{
	    	    		resMsg.obj =  new getResourceResponse(resId,null,filePath);
	    	    		resMsg.arg1 = Response.SUCCESS;
	    	    		resMsg.sendToTarget();
	    	    		return;
	    	    	}
	    			//get file name
	    			String fileName = "";
	    			Response response = resource.getInstance().GetResourceMetaInfo(sessionid, resId);
	    			if(response.errno != Response.SUCCESS)
	    			{
	    				resMsg.obj = new getResourceResponse(resId,response,filePath);
		            	resMsg.arg1 = response.errno;
		            	resMsg.sendToTarget();
	    				return;
	    			}
	    			fileName = (String)response.data.get("fileName");
	    			//get download key
	    			response = resource.getInstance().GetDownloadKey(sessionid,resId);
	            	Integer confirmId = (Integer)response.data.get("confirmId");
	            	String confirmKey = (String)response.data.get("confirmKey");
	            	if(response.errno != Response.SUCCESS)
	    			{
	            		resMsg.obj = new getResourceResponse(resId,response,filePath);
		            	resMsg.arg1 = response.errno;
		            	resMsg.sendToTarget();
	    				return;
	    			}
	            	//get file
	            	if(response.errno != Response.SUCCESS)
	    			{
	            		resMsg.obj = new getResourceResponse(resId,response,filePath);
		            	resMsg.arg1 = response.errno;
		            	resMsg.sendToTarget();
	    				return;
	    			}
	            	String bn_res = resource.getInstance().BinaryDownload(sessionid,resId,confirmId,confirmKey);
	            	//save file
	            	filePath = saveBinaryFile(bn_res,mOtherResDir+resId+"-"+fileName);
	            	//send res
	            	resMsg.obj = new getResourceResponse(resId,response,filePath);
	            	resMsg.arg1 = response.errno;
	            	resMsg.sendToTarget();
	    		}break;
	    		case PROFILE_IMAGE_REQUEST:
	    		{
	    			String filePath = checkLoaclCache(mProfileImageDir,""+resId);//check local cache
	    	    	if(null != filePath)
	    	    	{
	    	    		resMsg.obj =  new getResourceResponse(resId,null,filePath);
	    	    		resMsg.arg1 = Response.SUCCESS;
	    	    		resMsg.sendToTarget();
	    	    		return;
	    	    	}
	    			Response response = account.getInstanse().GetProfileImage(resId, "", sessionid);
	    			if(response.errno != Response.SUCCESS)
	    			{
	    				resMsg.obj = new getResourceResponse(resId,response,filePath);
		            	resMsg.arg1 = response.errno;
		            	resMsg.sendToTarget();
	    				return;
	    			}
	    			Bitmap profileImage = account.Base64Str2Bitmap((String)response.data.get("personImg"));
	    			filePath = saveBitmap(profileImage,mProfileImageDir+resId+".png");
	    			resMsg.obj = new getResourceResponse(resId,response,filePath);
	            	resMsg.arg1 = response.errno;
	            	resMsg.sendToTarget();
	    		}break;
	    		default:
	    		{}break;
    		}
    	}
    }

    public static String saveBitmap(Bitmap bm,String filename)
	{
		if(null == bm || null == filename)
		{
			return null;
		}
		File myCaptureFile = new File(filename);
        BufferedOutputStream bos = null;
		try 
		{
			bos = new BufferedOutputStream( new FileOutputStream(myCaptureFile));
		} catch (FileNotFoundException e1) 
		{
			// TODO Auto-generated catch block
			e1.printStackTrace();
			return null;
		}
		bm.compress(Bitmap.CompressFormat.PNG, 80, bos);
        try 
        {
			bos.flush();
	        bos.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		}
		return filename;
	}
    public static String saveBinaryFile(String payload,String filename)
    {
        try  
        {    
        	DataOutputStream out=new DataOutputStream(new FileOutputStream(filename));
            out.writeBytes(payload);
            out.close();  
        } catch (Exception e)  
        {  
            e.printStackTrace();
            return null;
        }
        return filename;
    }
    public class getResourceResponse
    {
    	public int resId = 0;
    	public Response httpRes = null;
    	public String filePath = null;
    	public getResourceResponse(int res_id,Response http_res,String path)
    	{
    		this.resId = res_id;
    		this.httpRes = http_res;
    		this.filePath = path; 
    	}
    }
    public Response getSheetList(boolean use_cache)
    {
    	String tag = ""+this.getUid();
    	if(use_cache)
    	{
    		String filePath = checkLoaclCache(mSheetDir,tag);//check local cache
        	if(null != filePath)
        	{
        		String jso_str = readString(filePath);
        		if(null == jso_str)
        		{
        			return null;
        		}
        		return Response.parse(jso_str);
        	}
    	}
    	Response res = sheet.getInstanse().GetSheetList(this.getSessionid());
    	if(res.errno == Response.SUCCESS)
    	{
    		String filePath = mSheetDir+tag+".dat";
    		if(null == writeString(filePath,res.mOriginalStr))
    		{
    			
    			return null;
    		}
    	}
    	return res;
    }   
    public Response getCategoryList(boolean use_cache,int sheetId)
    {
    	String tag = ""+sheetId;
    	if(use_cache)
    	{
    		String filePath = checkLoaclCache(mCategoryDir,tag);//check local cache
        	if(null != filePath)
        	{
        		String jso_str = readString(filePath);
        		if(null == jso_str)
        		{
        			return null;
        		}
        		return Response.parse(jso_str);
        	}
    	}
    	Response res = category.getInstanse().GetCategoryList(this.getSessionid(), sheetId);
    	if(res.errno == Response.SUCCESS)
    	{
    		String filePath = mCategoryDir+tag+".dat";
    		if(null == writeString(filePath,res.mOriginalStr))
    		{
    			return null;
    		}
    	}
    	return res;
    }
    
    public Response getProfileImage(boolean use_cache,int userId)
    {
    	String tag = ""+userId;
    	if(use_cache)
    	{
    		String filePath = checkLoaclCache(mProfileImageDir,tag);//check local cache
        	if(null != filePath)
        	{
        		File f = new File(filePath);
        		String jso_str = readString(filePath);
        		if(null == jso_str)
        		{
        			return null;
        		}
        		return Response.parse(jso_str);
        	}
    	}
    	Response res = account.getInstanse().GetProfileImage(userId,"", sessionid);
    	if(res.errno == Response.SUCCESS)
    	{
    		String filePath = mProfileImageDir+tag+".dat";
    		if(null == writeString(filePath,res.mOriginalStr))
    		{
    			return null;
    		}
    	}
    	return res;
    }
    public static String readString(String filePath)
    {
    	File f = new File(filePath);
		String str = "";
		try 
		{
			DataInputStream is = new DataInputStream(new FileInputStream(f));
			while(is.available()>0)
			{
				str = str+is.readUTF();
			}
			is.close();
		} catch (IOException e) 
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		}
		return str;
    }
    public static String writeString(String filePath,String str)
    {
		try  
        {    
        	DataOutputStream out=new DataOutputStream(new FileOutputStream(filePath));
        	FileOutputStream fs = new FileOutputStream(filePath);
        	String tmp = "";
        	for(int i = 0;i<str.length()/60000 + 1;i++)
        	{
        		if(i == str.length()/60000)
        		{
        			tmp = str.substring(i*60000,str.length());
        		}else
        		{
        			tmp = str.substring(i*60000,(i+1)*60000);
        		}
        		out.writeUTF(tmp);
        	}
            //out.writeChars(str);
            out.close();  
        } catch (Exception e)  
        {  
            e.printStackTrace();
            return null;
        }
		return filePath;
    }
}